<!--
Copyright Yahoo Inc.
SPDX-License-Identifier: Apache-2.0
-->
<template>
  <v-btn color="secondary">
    <template v-if="hotKeyEnabled && getShiftKeyHold">
      <span class="text-warning integration-view-hotkey-v">V</span>
    </template>
    <template v-else>
      <slot>
        Integration Views
      </slot>
    </template>
    <span v-if="showSelectedView && getSelectedView">
      {{ getSelectedView.name }}
    </span>
    <v-icon
      v-if="!noCaret"
      icon="mdi-menu-down"
      class="ml-1" />

    <v-menu
      v-model="menuOpen"
      activator="parent"
      location="bottom right"
      :close-on-content-click="false">
      <v-card class="view-selector-menu">
        <div class="d-flex flex-column">
          <div class="mx-1 my-1">
            <v-text-field
              class="mb-1"
              prepend-inner-icon="mdi-magnify"
              variant="outlined"
              v-model="viewSearch"
              ref="integrationViewDropdownSearchRef"
              @keydown.enter="attemptTopFilteredView"
              @focusin="setBarFocused"
              @focusout="setBarUnfocused" />

            <template
              v-for="(view, index) in filteredViews"
              :key="view._id">
              <v-btn
                density="compact"
                block
                variant="text"
                class="btn-space-between text-none view-selector-row"
                :class="{ small: true, 'top-searched-dropdown': index === 0 && barFocused }"
                @click="selectView(view)">
                <v-tooltip
                  v-if="view.name.length > 24"
                  location="right"
                  activator="parent"
                  close-on-content-click>
                  {{ view.name }}
                </v-tooltip>
                <div class="d-flex flex-row w-100 justify-space-between">
                  <div class="d-flex flex-row mw-75 flex-grow-1 justify-space-between align-center">
                    <v-icon
                      icon="mdi-share"
                      class="mr-1 cursor-help"
                      v-if="getUser && view.creator !== getUser.userId && !view._systemDefault"
                      v-tooltip="`Shared with you by ${view.creator}`" />
                    <span class="ellipsis no-overflow">
                      {{ view.name }}
                    </span>
                  </div>
                  <div v-if="view._editable">
                    <!-- cancel confirm delete button -->
                    <transition name="buttons">
                      <v-btn
                        size="x-small"
                        color="warning"
                        v-tooltip="'Cancel'"
                        title="Cancel"
                        class="float-right ml-1"
                        v-if="confirmDeleteView[view._id]"
                        @click.stop.prevent="toggleDeleteView(view._id)">
                        <v-icon icon="mdi-cancel" />
                      </v-btn>
                    </transition> <!-- /cancel confirm delete button -->
                    <!-- confirm delete button -->
                    <transition name="buttons">
                      <v-btn
                        size="x-small"
                        color="error"
                        v-tooltip="'Are you sure?'"
                        title="Are you sure?"
                        class="float-right ml-1"
                        v-if="confirmDeleteView[view._id]"
                        @click.stop.prevent="deleteView(view)">
                        <v-icon icon="mdi-check-bold" />
                      </v-btn>
                    </transition> <!-- /confirm delete button -->
                    <!-- delete button -->
                    <transition name="buttons">
                      <v-btn
                        size="x-small"
                        color="error"
                        class="square-btn-xs float-right ml-1"
                        v-if="!confirmDeleteView[view._id]"
                        v-tooltip:top="'Delete this view.'"
                        @click.stop.prevent="toggleDeleteView(view._id)">
                        <v-icon icon="mdi-trash-can" />
                      </v-btn>
                    </transition> <!-- /delete button -->
                  </div>
                </div>
              </v-btn>
              <hr
                :key="view._id + '-separator'"
                v-if="view._systemDefault && ((filteredViews[index + 1] && !filteredViews[index + 1]._systemDefault) || (!filteredViews[index + 1] && getViews.length === 0))"
                class="border-secondary my-0">
            </template>
            <v-list-item
              class="small"
              v-if="!getViews.length || !filteredViews.length">
              <template v-if="!getViews.length">
                No saved views.
              </template>
              <template v-else>
                No views match your search.
              </template>
            </v-list-item>
            <v-list-item
              v-if="error"
              variant="danger">
              <v-icon
                icon="mdi-alert" />
              {{ error }}
            </v-list-item>
          </div>
        </div>
      </v-card>
    </v-menu>
  </v-btn>
</template>

<script setup>
import UserService from '@/components/services/UserService';

import { reactive, ref, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
import { useGetters } from '@/vue3-helpers';
import { useRouter, useRoute } from 'vue-router';

const router = useRouter();
const route = useRoute();

const store = useStore();
const {
  getViews, getUser, getSelectedView,
  getAllViews, getShiftKeyHold, getFocusViewSearch
} = useGetters(store);

// Data
const error = ref('');
const viewSearch = ref('');
const filteredViews = ref([]);
const barFocused = ref('false');
const confirmDeleteView = reactive({});
const menuOpen = ref(false);
const integrationViewDropdownSearchRef = ref(null);

// Props
const props = defineProps({
  noCaret: {
    type: Boolean,
    default: false
  },
  showSelectedView: {
    type: Boolean,
    default: false
  },
  hotKeyEnabled: {
    type: Boolean,
    default: false
  }
});

// Methods
function selectView (view) {
  store.commit('SET_SELECTED_VIEW', view);
  store.commit('SET_SELECTED_INTEGRATIONS', view.integrations);
}

function toggleDeleteView (viewId) {
  confirmDeleteView[viewId] = !confirmDeleteView[viewId];
}

function deleteView (view) {
  // NOTE: this function handles fetching the updated view list and storing it
  UserService.deleteIntegrationsView(view._id).then(() => {
    if (view.name === getSelectedView.value) {
      menuOpen.value = false;
      store.commit('SET_SELECTED_VIEW', undefined);
    }
  }).catch((err) => {
    err.value = err.text || err;
    setTimeout(() => { err.value = ''; }, 5000);
  });
}

function filterViews (searchTerm) {
  if (!searchTerm) {
    filteredViews.value = JSON.parse(JSON.stringify(getAllViews.value));
    return;
  }

  const query = searchTerm.toLowerCase();
  filteredViews.value = getAllViews.value.filter((view) => {
    return view.name.toString().toLowerCase().match(query)?.length > 0;
  });
}

function attemptTopFilteredView () {
  if (filteredViews.value.length) {
    selectView(filteredViews.value[0]);
    menuOpen.value = false;
    viewSearch.value = '';
  }
}

function setBarFocused () {
  barFocused.value = true;
}

function setBarUnfocused () {
  barFocused.value = false;
}

// Watch
watch(menuOpen, (newOpen) => {
  if (newOpen) {
    viewSearch.value = '';
  }
});

watch(viewSearch, (searchTerm) => {
  filterViews(searchTerm);
});

watch(getViews, () => {
  filterViews(viewSearch.value);
});

watch(getSelectedView, (newView) => {
  const newViewIDParam = newView?._id;
  if (route.query.view !== newViewIDParam) {
    router.push({ query: { ...route.query, view: newViewIDParam } });
  }
});

watch(getFocusViewSearch, (val) => {
  if (props.hotKeyEnabled && val) { // shortcut for view dropdown search
    menuOpen.value = true;
    // we need a short timeout before we can focus the search bar within
    // the menu, since the input element is not rendered when closed
    setTimeout(() => {
      integrationViewDropdownSearchRef.value?.select();
    }, 100);
  }
});

onMounted(() => {
  filterViews(viewSearch.value);
});
</script>

<style>
.view-selector-menu {
  min-width: 12rem;
  max-width: 240px;
}
.view-selector-row {
  padding-inline: 0.25rem;
}
.top-searched-dropdown {
  background-color: var(--color-gray-light);
}
.integration-view-hotkey-v {
  /* pad the V shown when shifting to keep the button the same size */
  padding-inline: 0.16rem
}
</style>
